#pragma once

#include "WeiQiPaneWidget.h"
#include "ChessWidget.h"

#include "egui.h"

#define PANE_OFFSET 8
class CUIGoEventCallBack
{
public:
	virtual void OnUIMoveChess(int x,int y){};
};
class CChessGridContainer :
	public CContainerWidget , public CGoCallBackInterface
{
public:
	CChessGridContainer(void){
		m_bOfflineMode=FALSE;
		m_pCallBackToGoView=NULL;
		chessWidgets=NULL;
		m_pBlackMu=NULL;
		m_pWhiteMu=NULL;
	};
	virtual ~CChessGridContainer(void){
		if(chessWidgets!=NULL)
		{
			for(int x=0;x<game_size*game_size;x++)
			{
				if(*(chessWidgets+x)!=NULL)
				{
					delete (*(chessWidgets+x));
				}

			}
			delete 	chessWidgets;
		}

		if(m_pBlackMu!=NULL)
		{
			delete m_pWhiteMu;
			delete m_pBlackMu;
			m_pBlackMu=NULL;
			m_pWhiteMu=NULL;
		}
	};

	CDragon* m_pBlackMu;
	CDragon* m_pWhiteMu;
//	CMessageWidget* m_pMessageWidget;
	int game_size;
	int Move(int x, int y, int side);
	CWeiQiPaneWidget pane;
	CImageWidget cursor;
	int pane_x;
	int pane_y;
	int cell_size;
	int chess_size;
	int chess_cnt;
	WEIQI_SIDE_T cur_side;
	CChessWidget** chessWidgets;
	CLogicGo m_go;
	BOOL m_bOfflineMode;
	CUIGoEventCallBack* m_pCallBackToGoView;
	WEIQI_SIDE_T m_nMySide;
	
	static void HandleSocketEvent(void *pUserData, ModelEvent *pEvent)
	{

	}

	void InitListener()
	{
		GetEventListener()->pfnListener = HandleSocketEvent;

		GetEventListener()->pListenerData = this;
	}
	void init(WEIQI_SIDE_T mySide,int gameSize,int cellSize,int chessSize,CUIGoEventCallBack* pCallback,BOOL bOfflineMode=FALSE)
	{
		game_size=gameSize;
		cell_size=cellSize;
		chess_size=chessSize;
		m_nMySide=mySide;
		InitListener();
		m_bOfflineMode=bOfflineMode;
		
		m_go.init(gameSize,this,bOfflineMode);
		m_pCallBackToGoView=pCallback;

		chessWidgets=(CChessWidget**)malloc(game_size*game_size*sizeof(CChessWidget*));
		memset(chessWidgets,0,sizeof(CChessWidget*)*game_size*game_size);

		pane.init(gameSize,cellSize,PANE_OFFSET);
		if(m_bOfflineMode==TRUE)
		{
			cur_side=m_nMySide;
		}
		else
		{
			cur_side=WEIQI_SIDE_NULL;
		}
	}

	void ShowPane(int game_size,int x,int y)
	{

		char* draw_cmd = "H:1,0,0,470,470,1,";
		pane.setImage("resource/weiqipan.bmp",draw_cmd);
		WRect rc;
		rc.dx=game_size*cell_size+PANE_OFFSET*2;
		rc.dy=game_size*cell_size+PANE_OFFSET*2;
		rc.x=x;
		rc.y=y;		
		pane.SetRect(&rc);
	};

	void SocketMoveChess(WEIQI_SIDE_T chess_type,int x,int y)
	{
		m_go.MoveNoThink(x,y,chess_type);
		AddChess(chess_type,x,y);
	}

	void SocketDragonDead(WEIQI_SIDE_T side,unsigned int* dragon_dead)
	{
		CDragon* pDragon = new CDragon(side,dragon_dead,this->game_size);
		OnDragonKilled(pDragon);
		delete pDragon;


	}

	virtual void OnDragonKilled(CDragon* pDeadDragon)
	{
			for(int x=0;x<game_size;x++)
			{
				for(int y=0;y<game_size;y++)
				{
					if(pDeadDragon->IsInDragon(x,y)==TRUE)
					{
						RemoveChess(x,y);
					}
				}
			}
//			this->InvalidateContent(0);
	}
	virtual void OnNextTurn(WEIQI_SIDE_T side)
	{
		if(m_bOfflineMode==TRUE)
		{
			m_nMySide=side;
			cur_side=side;
		}
		if(m_nMySide!=side)
		{
			pane.HideCursor();
		}
		pane.RemoveMu();
		
	}
	BOOL MoveChess(WEIQI_SIDE_T chess_type,int x,int y)
	{
		return this->m_go.Move(x,y,chess_type);

	}

	CChessWidget* GetChessWidget(int x,int y)
	{

		int index=x+y*game_size;
		return *(chessWidgets+index);

	}

	void Pass(WEIQI_SIDE_T side)
	{	
		this->cur_side=ANOTHER_SIDE(side);

		if(m_bOfflineMode==TRUE)
		{
			m_nMySide=cur_side;
		}
	}



	void RemoveChess(int x,int y)
	{
		int index=x+y*game_size;

		WRect rc;
		CWidget* pW=(*(chessWidgets+index));
		pW->GetRect(&rc);

		RemoveWidget(pW);
		*(chessWidgets+index)=NULL;

		this->InvalidateClientArea(&rc);
		delete pW;

		
	}

	void AddChess(WEIQI_SIDE_T chess_type,int x,int y)
	{
		int index=x+y*game_size;
		CChessWidget* chess = new CChessWidget(chess_type,x,y);
		*(chessWidgets+index)=chess;
		WRect rc;
		rc.x=x*cell_size+pane_x+PANE_OFFSET-1;
		rc.y=y*cell_size+pane_y+PANE_OFFSET-1;
		rc.dx=cell_size;
		rc.dy=cell_size;
					int start = ::GetTickCount();
		//chess->SetAlpha(40);
		this->InsertWidget(chess,Z_ORDER_NORMAL+index);
		chess->SetRect(&rc);
		chess->InvalidateContent(0);
		chess_cnt++;
		
			TRACE_DEBUG(" Draw Chess time = %d \n",GetTickCount()-start);
	}


	void ListGame()
	{
		ModelEvent event;
		EVENT_LIST_GAME_T data;
		event.evCode = WEIQI_EVENT_LIST_GAME;
		data.ev_type=WEIQI_EVENT_LIST_GAME;

		memset(data.name,0,MAX_PLAYER_NAME);
		strcpy((char*)(data.name),"NoName");
		event.dwParam=(int)(&data); 
		GetEventModel()->Notify(&event);

	}
	BOOL CalculateCellIndex(int x,int y,int& x_index,int& y_index)
	{
		int dx=x-pane_x-PANE_OFFSET;
		int dy=y-pane_x-PANE_OFFSET;
		if((dx>=0 && dx<=game_size*cell_size)&&
			(dy>=0 && dy<=game_size*cell_size))			
		{
			x_index=dx/cell_size;
			y_index=dy/cell_size;
			int x_offset=dx % cell_size;
			int y_offset=dy % cell_size;
		//	if(x_offset>cell_size/2)
		//		x_index++;
		
		//	if(y_offset>cell_size/2)
		//		y_index++;
	
			if(x_index>=19) x_index=18;
			if(y_index>=19) y_index=18;

			if(x_index<=0)
				x_index=0;
			if(y_index<=0)
				y_index=0;
			return TRUE;
		}
		return FALSE;
	}
	void ShowCursor(char* filename,int x,int y)
	{

		
		return;
		int xindex,yindex;
		xindex=yindex=0;
		if(CalculateCellIndex(x,y,xindex,yindex)==TRUE && m_nMySide==cur_side)
		{
//			cursor.setImage(filename);
			WRect rc;
			rc.dx=cell_size;
			rc.dy=cell_size;
			rc.x=xindex*cell_size+pane_x;
			rc.y=yindex*cell_size+pane_y;		
			int start = ::GetTickCount();
			cursor.SetVisible(TRUE);
			cursor.SetRect(&rc);			
			TRACE_DEBUG(" Draw time = %d \n",GetTickCount()-start);
			cursor.InvalidateContent(0);

		}else
		{
			cursor.SetVisible(FALSE);
			//cursor.InvalidateContent(0);
			return;
		}		
	}
	void Display()
	{
//		pane.SetAlpha(40);
		InsertWidget(&pane,Z_ORDER_BACKGROUND);
		
		pane_x=0;
		pane_y=0;
	
		
		ShowPane(game_size,pane_x,pane_y);

		
		chess_cnt=0;


		
	}

	
	void SocketNextTurn(WEIQI_SIDE_T next_side)
	{

		cur_side=next_side;

		if(cur_side==m_nMySide)
		{
			cursor.SetVisible(TRUE);
			//cursor.InvalidateContent(0);

		}
		else
		{
			cursor.SetVisible(FALSE);
			//cursor.InvalidateContent(0);
			pane.HideCursor();


		}
		pane.RemoveMu();
	}
	void HandleLButtonUp(int x,int y)
	{
		int xindex,yindex;
		xindex=yindex=0;
		if(m_nMySide==cur_side)
		{
			if(CalculateCellIndex(x,y,xindex,yindex)==TRUE)
			{
				WEIQI_SIDE_T side = m_nMySide;
				if(m_bOfflineMode==TRUE)
				{
									int start = ::GetTickCount();

		
							if(MoveChess(side,xindex,yindex)==TRUE)
							{

									TRACE_DEBUG(" Cal Move Chess time = %d \n",GetTickCount()-start);
		
								AddChess(side,xindex,yindex);
								if(m_pCallBackToGoView!=NULL)
								{
									this->m_pCallBackToGoView->OnUIMoveChess(xindex,yindex);
								}
							}
				}
				else{
					if(m_pCallBackToGoView!=NULL)
					{			
						this->m_pCallBackToGoView->OnUIMoveChess(xindex,yindex);
					}
				}

			}
		}
		
	}
	virtual bool HandleMouseEvent(int evCode, WPoint* pPoint, int param2){
					WPoint pt;
			pt=*((WPoint*)pPoint);

		if(evCode==MOUSE_MOVE)
		{

			GetContainer()->ScreenToClient(&(pt.x),&(pt.y));
			if(this->m_bMouseLButtonHold==false && this->m_bEnableMouseMove==true)
			{




				if(cur_side==m_nMySide)
				{
					int xindex;
					int yindex;
					if(CalculateCellIndex(pt.x,pt.y,xindex,yindex)==TRUE)
					{
						pane.DisplayCursor(xindex,yindex);
					}
					else
					{
						pane.HideCursor();
					}
				}
				
			}
		}

		if(evCode==MOUSE_LBUTTON_UP)
		{		
					HandleLButtonUp(pt.x,pt.y);
		
		}

		return false;
	}
	void DisplayDianMuResult(unsigned int* black_mu,unsigned int * white_mu,int& num_black,int &num_white)
	{
		if(m_pBlackMu!=NULL)
		{
			delete m_pWhiteMu;
			delete m_pBlackMu;
			m_pBlackMu=NULL;
			m_pWhiteMu=NULL;
		}
		m_pBlackMu=new CDragon(WEIQI_SIDE_BLACK,black_mu ,game_size);
		m_pWhiteMu=new CDragon(WEIQI_SIDE_WHITE,white_mu,game_size);
		this->pane.DrawMu(m_pBlackMu,m_pWhiteMu);

		for(int x=0;x<game_size;x++)
		{
			for(int y=0;y<game_size;y++)
			{
		
				if(m_pBlackMu!=NULL)
				{
					if(m_pBlackMu->IsInDragon(x,y))
					{
						num_black++;
					}
				}

				if(m_pWhiteMu!=NULL)
				{
					if(m_pWhiteMu->IsInDragon(x,y))
					{
						num_white++;
					}
				}
			}
		}
	}
	void DianMu(int& numBlack,int& numWhite)
	{
		if(m_pBlackMu!=NULL)
		{
			delete m_pWhiteMu;
			delete m_pBlackMu;
			m_pBlackMu=NULL;
			m_pWhiteMu=NULL;
		}
	
		m_pBlackMu= new CDragon(WEIQI_SIDE_BLACK,game_size);
		m_pWhiteMu= new CDragon(WEIQI_SIDE_WHITE,game_size);
		this->m_go.DianMu(m_pBlackMu,m_pWhiteMu);
		this->pane.DrawMu(m_pBlackMu,m_pWhiteMu);

		for(int x=0;x<game_size;x++)
		{
			for(int y=0;y<game_size;y++)
			{
		
				if(m_pBlackMu!=NULL)
				{
					if(m_pBlackMu->IsInDragon(x,y))
					{
						numBlack++;
					}
				}

				if(m_pWhiteMu!=NULL)
				{
					if(m_pWhiteMu->IsInDragon(x,y))
					{
						numWhite++;
					}
				}
			}
		}
	}
};
